﻿using AppWebService;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SelfService.Model.Models;
using SelfService.XinXing.Models;
using WalkingTec.Mvvm.Core;

namespace SelfService.XinXing
{
    public class PayService : BackgroundService
    {
        private readonly IServiceProvider _service;
        private readonly AutoWebServiceSoapClient _appClient;
        private readonly ReservationConfig _config;

        public PayService(IServiceProvider service, IOptions<ReservationConfig> options, AppWebService.AutoWebServiceSoapClient appClient)
        {
            _service = service;
            _appClient = appClient;
            _config = options.Value;
        }

        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            return Task.Factory.StartNew(async () =>
            {
                do
                {
                    var scope = _service.CreateScope();
                    var wtm = scope.ServiceProvider.GetRequiredService<WTMContext>();
                    try
                    {
                        var orders = await wtm.DC.Set<SysPay>()
                            .Include(e => e.Client)
                            .Include(e => e.Patient)
                            .Where(e => e.CreateTime > DateTime.Now.AddMinutes(-3) && e.PayStatus == PayStatusEnum.待支付)
                            .ToListAsync(cancellationToken: stoppingToken);
                        foreach (var order in orders)
                        {
                            var request = new HisPayResultRequest();
                            request.Zffs = "0E";
                            request.OutTradeNo = order.OutOrderNo;
                            request.CardNo = order.Patient.CardNo;
                            request.UserId = order.CreateBy;
                            request.Ip = order.Client?.Ip ?? "";
                            var xml = request.ToXml();
                            string response = string.Empty;
                            try
                            {
                                response = await _appClient.GetValueAsync(xml);
                                if (response.XmlTryParseToObject(out HisPayResultResponse result))
                                {
                                    if (result.ResultCode == "0")
                                    {
                                        if (result.TradeStatus == "TRADE_SUCCESS" || result.TradeStatus == "TRADE_FINISHED")
                                        {
                                            order.PayStatus = PayStatusEnum.支付成功;
                                            order.PayTime = DateTime.Now;
                                            order.UpdateBy = "PayService";
                                            order.UpdateTime = DateTime.Now;
                                            await wtm.DC.SaveChangesAsync(stoppingToken);
                                            if (order.Use == PayUseEnum.门诊充值)
                                            {
                                                var addCreditRequest = new HisCreditRequest();
                                                addCreditRequest.Zffs = "0E";
                                                addCreditRequest.CardNo = order.Patient.CardNo;
                                                addCreditRequest.TotalAmount = Math.Round(order.Amount, 2);
                                                addCreditRequest.OutTradeNo = order.OutOrderNo;
                                                addCreditRequest.TradeNo = order.OutOrderNo;
                                                addCreditRequest.Jyrq = order.PayTime?.ToString("yyyy-MM-dd HH:mm:ss");
                                                addCreditRequest.OperatorId = order.CreateBy;
                                                addCreditRequest.UserId = order.CreateBy;
                                                addCreditRequest.Ip = order.Client?.Ip ?? "";
                                                var requestXml = addCreditRequest.ToXml();
                                                var addCreditResponse = await _appClient.GetValueAsync(requestXml);
                                                wtm.DoLog($"充值. 请求数据:{JsonConvert.SerializeObject(addCreditRequest)}, 返回值:{response}");
                                                if (addCreditResponse.XmlTryParseToObject(out HisCreditResponse addCreditResult))
                                                {
                                                    if (addCreditResult.ResultCode == "0")
                                                    {
                                                        order.UseStatus = UseStatusEnum.成功;
                                                        order.UseMessage = addCreditResult.OutTradeNo;
                                                    }
                                                    else
                                                    {
                                                        order.UseStatus = UseStatusEnum.失败;
                                                        order.UseMessage = addCreditResult.ErrorMsg;
                                                    }
                                                }
                                                else
                                                {
                                                    order.UseStatus = UseStatusEnum.失败;
                                                    order.UseMessage = addCreditResponse;
                                                }
                                                await wtm.DC.SaveChangesAsync(stoppingToken);
                                            }
                                        }
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                wtm.DoLog($"查询订单出错, 请求信息{JsonConvert.SerializeObject(xml)}, 返回信息:{response} 异常信息:{JsonConvert.SerializeObject(e)}", ActionLogTypesEnum.Exception, "新星支付", "PayService");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        wtm.DoLog($"支付结果检查服务异常:{JsonConvert.SerializeObject(e)}", ActionLogTypesEnum.Exception, "新星支付", "PayService");
                    }
                    await Task.Delay(3000, stoppingToken);
                } while (!stoppingToken.IsCancellationRequested);
            }, stoppingToken);
        }
    }
}
